﻿using KalevaAalto.DataPart.Enums;
using KalevaAalto.DataPart.Models;
using KalevaAalto.TypePart;
using Org.BouncyCastle.Asn1.X509.Qualified;
using Spire.Xls;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace KalevaAalto.DataPart.DataBasePart.Attributes
{
    [AttributeUsage(AttributeTargets.Property, Inherited = true)]
    public class DataColumnAttribute : SqlSugar.SugarColumn, IStyle
    {
        public DataColumnAttribute() : base()
        {

        }

        public DataColumnAttribute(Type type) :this()
        {

            if (type.IsOrNullableInteger() || type.IsOrNullableUInteger()) { Width = 10; NumberFormat = @"#,##0"; HorizontalAlignment = HorizontalAlignment.Right; }
            else if (type.IsOrNullableFloat() || type.IsOrNullableDecimal()) { Width = 12; NumberFormat = @"#,##0.00"; HorizontalAlignment = HorizontalAlignment.Right; }
            else if (type.IsOrNullableChar()) { Width = 6; }
            else if (type.IsOrNullableBool()){ Width = 8; }
            else if (type.IsOrNullableDateTime())  { NumberFormat = @"yyyy-MM-dd"; }
            else if (type.IsByteArray()) { Width = 20; HorizontalAlignment = HorizontalAlignment.Left; WrapText = true; }
        }

        public DataColumnAttribute(string columnName,Type type):this(type)
        {
            ColumnName = columnName;
        }

        public double Width { get; set; } = 12;
        public bool WrapText { get; set; } = false;
        public HorizontalAlignment HorizontalAlignment { get; set; } = HorizontalAlignment.Center;
        public VerticalAlignment VerticalAlignment { get; set; } = VerticalAlignment.Center;

        public string NumberFormat { get; set; } = string.Empty;

        public IFont Font => new Font();
        public IFill Fill => new Fill();
        public FontWeight FontWeight { get => Font.Weight; set => Font.Weight = value; }
        public float FontSize { get => Font.Size; set => Font.Size = value; }
        public System.Drawing.Color FontColor { get => Font.Color; set => Font.Color = value; }
        public string FontName { get => Font.Name; set => Font.Name = value; }

        public IBorder Border { get; set; } = new Border();



        public DataColumnAttribute(string columnName)
        {
            ColumnName = columnName;
        }


        private static DataColumnAttribute GetDataColumnStyle(string columnName, Type type)
        {
            return new DataColumnAttribute(columnName,type);
        }

        public static DataColumnAttribute GetDataColumnStyle<T>(string columnName)
        {
            return GetDataColumnStyle(columnName, typeof(T));
        }

        public static ICollection<DataColumnAttribute> GetDataColumnStyles(Type objType, IEnumerable<DataColumnAttribute>? dataColumnStyles = null)
        {
            ICollection<DataColumnAttribute> result = new List<DataColumnAttribute>();
            dataColumnStyles = dataColumnStyles?.ToArray() ?? Array.Empty<DataColumnAttribute>();
            IDictionary<string, PropertyInfo> columnInfos = GetColumnInfoDic(objType);

            foreach (var item in columnInfos)
            {
                if (dataColumnStyles.Any(it => it.ColumnName == item.Key)) result.Add(dataColumnStyles.First(it => it.ColumnName == item.Key));
                DataColumnAttribute? dataColumnStyle = item.Value.GetCustomAttribute<DataColumnAttribute>();
                if (dataColumnStyle is null)
                {
                    dataColumnStyle = GetDataColumnStyle(item.Key, item.Value.PropertyType);
                }
                else
                {
                    dataColumnStyle.ColumnName = item.Key;
                }
                result.Add(dataColumnStyle);
            }

            return result;
        }


        public static ICollection<DataColumnAttribute> GetDataColumnStyles(ICollection<KeyValuePair<string, Type>> valuePairs, IEnumerable<DataColumnAttribute>? dataColumnStyles = null)
        {
            ICollection<DataColumnAttribute> result = new List<DataColumnAttribute>();

            dataColumnStyles = dataColumnStyles?.ToArray() ?? Array.Empty<DataColumnAttribute>();
            foreach (var item in valuePairs)
            {
                if (dataColumnStyles.Any(it => it.ColumnName == item.Key)) result.Add(dataColumnStyles.First(it => it.ColumnName == item.Key));
                else result.Add(GetDataColumnStyle(item.Key, item.Value));
            }

            return result;
        }

        public static ICollection<DataColumnAttribute> GetDataColumnStyles(DataTable dataTable, IEnumerable<DataColumnAttribute>? dataColumnStyles = null)
        {
            return GetDataColumnStyles(dataTable.Columns.Cast<DataColumn>().Select(it => new KeyValuePair<string, Type>(it.ColumnName, it.DataType)).ToArray(), dataColumnStyles);
        }



    }
}
